<template>
	<view class="container">
		<u-grid :col="5" :gutter="30">
			<u-grid-item @click="showData(item,index)" v-for="(item, index) in weekData" :key="index">
				<!-- <u-icon name="github-circle-fill" :size="46" color="#409EFF"></u-icon> -->
				<u-icon name="github-circle-fill" :size="46"
					:color="selectedIndex === index ? 'red' : '#409EFF'"></u-icon>
				<text class="grid-text">第{{ item }}周</text>
			</u-grid-item>
			<u-grid-item @click="goJiFenChart()">
				<u-icon name="photo-fill" :size="46" color="#FF66FF"></u-icon>
				<text class="grid-text">趋势图</text>
			</u-grid-item>
			<u-grid-item @click="exportToImage()">
				<u-icon name="download" color="#2979ff" size="46"></u-icon>
				<text class="grid-text">下载</text>
			</u-grid-item>
		</u-grid>
		<!-- 隐藏的canvas -->
		<canvas canvas-id="exportCanvas" :style="{ 
			width: canvasWidth + 'px', 
			height: canvasHeight + 'px', 
			position: 'absolute', 
			left: '-9999px'
		}"></canvas>
		<view v-if="showDialog">
			<view class="form-group">
				<label for="start-class">起始班级：</label>
				<input type="number" v-model="startClass" placeholder="请输入起始班级序号" />
			</view>

			<view class="form-group">
				<label for="end-class">结束班级：</label>
				<input type="number" v-model="endClass" placeholder="请输入结束班级序号" />
			</view>

			<view class="form-group">
				<label for="score-threshold">指定分数(>=)：</label>
				<input type="number" v-model="scoreThreshold" placeholder="默认为0" />
			</view>

			<view class="form-group">
				<label for="sort-by">排序方式：</label>
				<picker style="font-weight: bold;" mode="selector" :range="sortOptions" @change="onSortChange">
					<view>{{ sortOptions[sortByIndex] }}</view>
				</picker>
			</view>

			<view class="table-container">
				<table>
					<thead>
						<tr>
							<th class="sticky-col">班级</th>
							<th>平均分</th>
							<th>积分</th>
							<th>排名</th>
							<th>最高分</th>
							<th>最低分</th>
							<th>超指定分数</th>
							<th>优秀人数</th>
							<th>优秀率</th>
							<th>及格人数</th>
							<th>及格率</th>
							<th>120</th>
							<th>[114,120)</th>
							<th>[108,114)</th>
							<th>[102,108)</th>
							<th>[96,102)</th>
							<th>[84,96)</th>
							<th>[72,84)</th>
							<th>[60,72)</th>
							<th>[48,60)</th>
							<th>[0,48)</th>
						</tr>
					</thead>
					<tbody>
						<tr v-for="(item, index) in classAvg" :key="index">
							<td class="sticky-col">{{ item.className }}</td>
							<td>{{ item.avgScore.toFixed(2) }}</td>
							<td>{{ item.totalPoints }}</td>
							<td>{{ item.rank }}</td>
							<td>{{ item.maxScore }}</td>
							<td>{{ item.minScore }}</td>
							<td>{{ item.thresholdCount }}</td>
							<td>{{ item.excellentCount }}</td>
							<td>{{ item.excellentRate.toFixed(2) }}%</td>
							<td>{{ item.passCount }}</td>
							<td>{{ item.passRate.toFixed(2) }}%</td>
							<td>{{ item.segmentCounts['120'] }}</td>
							<td>{{ item.segmentCounts['[114,120)'] }}</td>
							<td>{{ item.segmentCounts['[108,114)'] }}</td>
							<td>{{ item.segmentCounts['[102,108)'] }}</td>
							<td>{{ item.segmentCounts['[96,102)'] }}</td>
							<td>{{ item.segmentCounts['[84,96)'] }}</td>
							<td>{{ item.segmentCounts['[72,84)'] }}</td>
							<td>{{ item.segmentCounts['[60,72)'] }}</td>
							<td>{{ item.segmentCounts['[48,60)'] }}</td>
							<td>{{ item.segmentCounts['[0,48)'] }}</td>
						</tr>
					</tbody>
				</table>
			</view>
		</view>
	</view>
</template>

<script>
	import html2canvas from 'html2canvas';
	export default {
		data() {
			return {
				showDialog: false,
				weekData: [],
				data: [],
				dataNum: 0,
				selectedIndex: null, // 用于保存被点击的索引
				startClass: 701, // 起始班级
				endClass: 727, // 结束班级
				scoreThreshold: 0, // 指定分数
				sortByIndex: 0, // 排序方式索引
				sortOptions: ["积分", "平均分", "最高分", "指定分数", "优秀率", "及格率"], // 排序选项
				classAvg: [], // 处理后的班级数据
				canvasWidth: 3000,
				canvasHeight: 4000,
				isCalculating: false, // 计算状态锁
				calculationRetry: 0, // 重试计数器
				colWidths: [], // 改为空数组，动态计算
				headerTitles: [
					'班级', '平均分', '积分', '排名', '最高分', '最低分',
					'超分数', '优秀数', '优秀率', '及格数', '及格率',
					'120', '[114,120)', '[108,114)', '[102,108)', '[96,102)',
					'[84,96)', '[72,84)', '[60,72)', '[48,60)', '[0,48)'
				]
			};
		},
		watch: {
			startClass: "handleDataChange",
			endClass: "handleDataChange",
			scoreThreshold: "handleDataChange",
			sortByIndex: "handleDataChange",
		},
		mounted() {
			this.weekData = uni.getStorageSync("龙湖四中周数");
			console.log(this.weekData);
			console.log("周数", uni.getStorageSync("龙湖四中周数"));
		},
		methods: {

			// 导出表格为图片
			// 在exportToImage方法中添加详细错误处理
			async exportToImage() {
				try {
					// 1. 重置状态
					this.colWidths = [];
					await this.$nextTick();

					// 2. 计算列宽
					await this.calculateColWidths();
					console.log('列宽计算完成，开始绘制');

					// 3. 获取表格尺寸
					const rect = await new Promise(resolve => {
						uni.createSelectorQuery()
							.in(this)
							.select('.table-container')
							.boundingClientRect(resolve)
							.exec();
					});

					// 4. 设置高清画布
					const dpr = uni.getSystemInfoSync().pixelRatio;
					const canvasWidth = this.colWidths.reduce((a, b) => a + b, 0) * dpr;
					const canvasHeight = (this.classAvg.length + 1) * 40 * dpr; // 40px行高

					this.canvasWidth = canvasWidth;
					this.canvasHeight = canvasHeight;
					await this.$nextTick();

					// 5. 初始化画布
					const ctx = uni.createCanvasContext('exportCanvas', this);
					ctx.scale(dpr, dpr);

					// 6. 绘制背景
					ctx.setFillStyle('#FFFFFF');
					ctx.fillRect(0, 0, canvasWidth / dpr, canvasHeight / dpr);

					// 7. 绘制表格
					await this.drawTable(ctx);
					console.log('表格绘制完成');

					// 8. 生成图片
					const tempFilePath = await new Promise((resolve, reject) => {
						ctx.draw(false, () => {
							uni.canvasToTempFilePath({
								canvasId: 'exportCanvas',
								success: res => resolve(res.tempFilePath),
								fail: reject,
							}, this);
						});
					});
					console.log('临时文件路径:', tempFilePath);

					// 9. 保存到相册
					await this.saveImage(tempFilePath);
					console.log('图片保存完成');

				} catch (err) {
					console.error('导出失败:', err);
					uni.showToast({
						title: `请先选中数据！`,
						icon: 'none',
						duration: 3000
					});
				}
			},

			// 增强版saveImage方法
			async saveImage(tempPath) {
				try {
					// 1. 检查权限
					const {
						authSetting
					} = await uni.getSetting();
					if (!authSetting['scope.writePhotosAlbum']) {
						const {
							confirm
						} = await uni.showModal({
							title: '需要相册权限',
							content: '请允许保存图片到相册',
							confirmText: '去授权'
						});

						if (confirm) {
							await uni.openSetting();
						} else {
							throw new Error('用户取消授权');
						}
					}

					// 2. 保存图片
					await new Promise((resolve, reject) => {
						uni.saveImageToPhotosAlbum({
							filePath: tempPath,
							success: resolve,
							fail: (err) => {
								console.error('保存错误:', err);
								reject(new Error('保存失败，请检查权限'));
							}
						});
					});

					uni.showToast({
						title: '保存成功',
						icon: 'success'
					});

				} catch (err) {
					console.error('保存失败:', err);
					throw err; // 抛出错误给上层处理
				}
			},
			// 动态计算列宽
			// 修改后的 calculateColWidths 方法
			async calculateColWidths() {
				if (this.isCalculating) {
					console.warn('计算正在进行中，跳过重复请求');
					return;
				}

				this.isCalculating = true;
				this.calculationRetry = 0;

				try {
					const {
						headerWidths,
						dataWidths
					} = await this.getColumnDimensions();

					// 合并列宽（取最大值）
					this.colWidths = headerWidths.map((hw, i) => {
						return Math.max(hw, dataWidths[i] || 0);
					});

					// 强制转换为整数并限制最小宽度
					this.colWidths = this.colWidths.map(w => {
						const intWidth = Math.ceil(w);
						return Math.max(intWidth, 60); // 确保最小宽度60
					});

					console.log('最终整数列宽:', JSON.stringify(this.colWidths));
					console.log('总宽度:', this.colWidths.reduce((a, b) => a + b, 0));

					// 宽度验证
					if (this.colWidths.length !== this.headerTitles.length) {
						throw new Error(`列宽数量不匹配，预期${this.headerTitles.length}列，实际${this.colWidths.length}列`);
					}

					if (this.colWidths.some(w => w <= 0)) {
						throw new Error('存在无效列宽值');
					}

				} catch (err) {
					console.error('列宽计算失败:', err);

					// 重试机制（最多3次）
					if (this.calculationRetry < 3) {
						this.calculationRetry++;
						await this.$nextTick();
						return this.calculateColWidths();
					} else {
						throw new Error('列宽计算失败，请检查表格结构');
					}

				} finally {
					this.isCalculating = false;
				}
			},

			// 分离维度获取方法
			async getColumnDimensions() {
				return new Promise((resolve, reject) => {
					const query = uni.createSelectorQuery().in(this);
					let headerDone = false;
					let dataDone = false;
					let headerWidths = [];
					let dataWidths = [];

					// 表头查询
					query.selectAll('th').boundingClientRect(ths => {
						if (!ths || ths.length === 0) {
							reject(new Error('表头元素未找到'));
							return;
						}

						headerWidths = ths.map(th => {
							return th.width * 1.1 + 10; // 增加10%余量
						});
						headerDone = true;
						checkReady();
					}).exec();

					// 数据查询
					query.selectAll('td').boundingClientRect(tds => {
						if (!tds || tds.length === 0) {
							dataDone = true;
							checkReady();
							return;
						}

						dataWidths = new Array(this.headerTitles.length).fill(0);
						tds.forEach((td, index) => {
							const colIndex = index % this.headerTitles.length;
							const width = td.width * 1.1 + 10; // 增加10%余量
							if (width > dataWidths[colIndex]) {
								dataWidths[colIndex] = width;
							}
						});
						dataDone = true;
						checkReady();
					}).exec();

					// 超时处理（3秒）
					const timeout = setTimeout(() => {
						reject(new Error('维度查询超时'));
					}, 3000);

					function checkReady() {
						if (headerDone && dataDone) {
							clearTimeout(timeout);
							resolve({
								headerWidths,
								dataWidths
							});
						}
					}
				});
			},
			async drawTable(ctx) {
				const rowHeight = 40;
				let x = 0; // 初始化 x 位置

				// 绘制表头
				ctx.setFillStyle('#409EFF'); // 蓝色背景
				ctx.fillRect(0, 0, this.colWidths.reduce((a, b) => a + b), rowHeight);

				ctx.setFontSize(14);
				ctx.setFillStyle('#FFFFFF'); // 白色字体
				ctx.setTextBaseline('middle');

				// 绘制表头文本
				this.headerTitles.forEach((text, i) => {
					ctx.fillText(text, x + 10, rowHeight / 2);
					x += this.colWidths[i];
				});

				// 绘制数据行
				ctx.setFontSize(12);
				ctx.setFillStyle('#000000'); // 黑色字体

				this.classAvg.forEach((item, rowIndex) => {
					const yPos = (rowIndex + 1) * rowHeight;

					// 交替行背景色
					if (rowIndex % 2 === 0) {
						ctx.setFillStyle('#f8f9fa');
						ctx.fillRect(0, yPos, this.colWidths.reduce((a, b) => a + b), rowHeight);
					}

					let xPos = 0; // 重置 xPos

					const cells = [
						item.className,
						item.avgScore.toFixed(2),
						item.totalPoints,
						item.rank,
						item.maxScore,
						item.minScore,
						item.thresholdCount,
						item.excellentCount,
						item.excellentRate.toFixed(2) + '%',
						item.passCount,
						item.passRate.toFixed(2) + '%',
						...Object.values(item.segmentCounts)
					];

					// 绘制每一列的单元格
					cells.forEach((cell, colIndex) => {
						// 为排名列单独设置字体颜色
						if (colIndex === 3) { // 假设排名是第4列（索引从0开始）
							ctx.setFillStyle('#FF0000'); // 设置红色字体
						} else {
							ctx.setFillStyle('#000000'); // 其他列使用黑色字体
						}

						ctx.setFontSize(12); // 设置字体大小为12
						ctx.fillText(cell, xPos + 10, yPos + rowHeight / 2); // 绘制文本
						xPos += this.colWidths[colIndex]; // 更新 xPos
					});
				});

				// 绘制网格线
				ctx.setStrokeStyle('#e0e0e0');
				this.drawGridLines(ctx, rowHeight);
			},

			// 绘制网格线
			drawGridLines(ctx, rowHeight) {
				// 垂直列线
				let x = 0;
				this.colWidths.forEach(width => {
					x += width;
					ctx.beginPath();
					ctx.moveTo(x, 0);
					ctx.lineTo(x, (this.classAvg.length + 1) * rowHeight);
					ctx.stroke();
				});

				// 水平行线
				for (let y = rowHeight; y <= (this.classAvg.length + 1) * rowHeight; y += rowHeight) {
					ctx.beginPath();
					ctx.moveTo(0, y);
					ctx.lineTo(this.colWidths.reduce((a, b) => a + b), y);
					ctx.stroke();
				}
			},
			async saveImage(tempPath) {
				await uni.saveImageToPhotosAlbum({
					filePath: tempPath,
					success: () => {
						uni.showToast({
							title: '已保存到相册',
							icon: 'success'
						});
					},
					fail: () => {
						uni.showToast({
							title: '保存失败，请检查权限',
							icon: 'none'
						});
					},
				})
			},
			handleDataChange() {
				this.showData(this.dataNum, this.selectedIndex);
			},
			goJiFenChart() {
				uni.navigateTo({
					url: '/pages/index/jiFenChart',
					animationType: 'fade-in',
					animationDuration: 200
				});
			},
			// 处理数据
			showData(num, index) {
				this.dataNum = num;
				// 设置当前选中的项索引
				this.selectedIndex = index;
				this.showDialog = true;
				// 从本地存储中获取数据并赋值给 data
				let data = uni.getStorageSync("积分计算数据" + this.dataNum) || [];

				// 从 this 对象中解构其他值
				const {
					startClass,
					endClass,
					scoreThreshold,
					sortByIndex
				} = this;

				// 组织班级数据
				const classData = {};

				data.forEach(item => {
					const className = item.student_class;
					const score = item.score;

					// 如果班级不在指定范围内，则跳过
					if (className < startClass || className > endClass) {
						return;
					}

					// 确保成绩为数字
					const numericScore = parseFloat(score);
					if (!isNaN(numericScore)) {
						if (!classData[className]) {
							classData[className] = {
								totalScore: 0,
								count: 0,
								maxScore: -Infinity,
								minScore: Infinity,
								thresholdCount: 0,
								excellentCount: 0,
								passCount: 0,
								totalPoints: 0,
								segmentCounts: {
									'120': 0,
									'[114,120)': 0,
									'[108,114)': 0,
									'[102,108)': 0,
									'[96,102)': 0,
									'[84,96)': 0,
									'[72,84)': 0,
									'[60,72)': 0,
									'[48,60)': 0,
									'[0,48)': 0
								}
							};
						}
						// classData[className].totalScore += numericScore;
						// classData[className].count += 1;
						// 排除0分学生
						if (numericScore !== 0) {
							classData[className].totalScore += numericScore;
							classData[className].count += 1;
						}
						classData[className].maxScore = Math.max(classData[className].maxScore,
							numericScore);
						classData[className].minScore = Math.min(classData[className].minScore,
							numericScore);

						if (numericScore >= scoreThreshold) {
							classData[className].thresholdCount += 1;
						}

						if (numericScore >= 96) {
							classData[className].excellentCount += 1;
						}

						if (numericScore >= 72) {
							classData[className].passCount += 1;
						}

						// 计算积分
						if (numericScore == 120) {
							classData[className].totalPoints += 15;
							classData[className].segmentCounts['120'] += 1;
						} else if (numericScore >= 114) {
							classData[className].totalPoints += 14;
							classData[className].segmentCounts['[114,120)'] += 1;
						} else if (numericScore >= 108) {
							classData[className].totalPoints += 12;
							classData[className].segmentCounts['[108,114)'] += 1;
						} else if (numericScore >= 102) {
							classData[className].totalPoints += 10;
							classData[className].segmentCounts['[102,108)'] += 1;
						} else if (numericScore >= 96) {
							classData[className].totalPoints += 8;
							classData[className].segmentCounts['[96,102)'] += 1;
						} else if (numericScore >= 84) {
							classData[className].totalPoints += 6;
							classData[className].segmentCounts['[84,96)'] += 1;
						} else if (numericScore >= 72) {
							classData[className].totalPoints += 4;
							classData[className].segmentCounts['[72,84)'] += 1;
						} else if (numericScore >= 60) {
							classData[className].totalPoints += 2;
							classData[className].segmentCounts['[60,72)'] += 1;
						} else if (numericScore >= 48) {
							classData[className].totalPoints += 1;
							classData[className].segmentCounts['[48,60)'] += 1;
						} else if (numericScore >= 0) {
							classData[className].totalPoints += 0;
							classData[className].segmentCounts['[0,48)'] += 1;
						}
					}
				});

				// 计算班级的平均分、优秀率和及格率
				const classAvg = [];
				for (const className in classData) {
					// const avgScore = classData[className].totalScore / classData[className].count;
					// 修改为
					const avgScore = classData[className].count === 0 ?
						0 :
						classData[className].totalScore / classData[className].count;
					const excellentRate = (classData[className].excellentCount / classData[className]
						.count) * 100;
					const passRate = (classData[className].passCount / classData[className].count) * 100;
					classAvg.push({
						className,
						avgScore,
						maxScore: classData[className].maxScore,
						minScore: classData[className].minScore,
						thresholdCount: classData[className].thresholdCount,
						excellentCount: classData[className].excellentCount,
						excellentRate,
						passCount: classData[className].passCount,
						passRate,
						totalPoints: classData[className].totalPoints,
						segmentCounts: classData[className].segmentCounts
					});
				}

				// 按照用户选择的方式排序
				const sortBy = this.sortOptions[sortByIndex];
				classAvg.sort((a, b) => {
					switch (sortBy) {
						case "平均分":
							return b.avgScore - a.avgScore;
						case "最高分":
							return b.maxScore - a.maxScore;
						case "指定分数":
							return b.thresholdCount - a.thresholdCount;
						case "优秀率":
							return b.excellentRate - a.excellentRate;
						case "及格率":
							return b.passRate - a.passRate;
						case "积分":
							return b.totalPoints - a.totalPoints;
						default:
							return b.avgScore - a.avgScore;
					}
				});

				// 给每个班级排名
				classAvg.forEach((item, index) => {
					item.rank = index + 1;
				});

				this.classAvg = classAvg;
			},
			// 排序方式改变
			onSortChange(e) {
				this.sortByIndex = e.detail.value;
				this.showData(this.dataNum, this.selectedIndex);
			},
		},
	};
</script>

<style scoped>
	.sticky-col {
		position: sticky;
		left: 0;
		background-color: green;
		/* 可以设置背景色，避免背景与滚动内容重叠 */
		z-index: 1;
		color: white;
		/* 确保固定列在前 */
	}

	/* 强制表格稳定渲染 */
	.table-container table {
		table-layout: fixed;
		width: max-content;
	}

	th,
	td {
		min-width: 60px;
		/* 与代码中的最小宽度一致 */
		padding: 8px 12px;
		box-sizing: border-box;
	}

	th.sticky-col {
		z-index: 2;
		/* 确保表头固定 */
	}

	.grid-item {
		background-color: #ffffff;
		border-radius: 10px;
		padding: 20px;
		box-shadow: 0 2rpx 8rpx 0 rgba(0, 0, 0, 0.1);
		transition: transform 0.3s ease, box-shadow 0.3s ease;
	}

	.grid-item:hover {
		transform: translateY(-5px);
		box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15);
	}

	.grid-text {
		font-size: 16px;
		color: #606266;
		margin-top: 10px;
		font-weight: bold;
	}

	.container {
		padding: 20px;
	}

	.form-group {
		margin-bottom: 15px;
	}

	label {
		margin-right: 10px;
	}

	input {
		padding: 5px;
		border: 1px solid #ccc;
		border-radius: 4px;
	}

	/* .table-container {
		overflow-x: auto;
	} */
	/* 添加防止表格溢出的样式 */
	.table-container {
		overflow: auto;
	}

	table {
		width: 100%;
		border-collapse: collapse;
		margin-top: 20px;
		min-width: 1000px;
		/* 确保表格最小宽度 */
	}

	th,
	td {
		padding: 10px;
		border: 1px solid #ddd;
		text-align: center;
	}

	th {
		background-color: #007bff;
		color: white;
	}

	tr:nth-child(even) {
		background-color: #f2f2f2;
	}
</style>